ECMAScript for XML (E4X)とはECMAScriptが直接XMLを扱えるようにする言語拡張の仕様であり、ECMAの標準(Standard ECMA-357 ECMAScript for XML (E4X) Specification)です。
E4Xは、MozillaプロジェクトのJavaで実装されたECMAScriptの処理系Rhinoの1.6R1に実装されています。
このコンテンツは、檜山正幸さんと山本陽平さんからのE4Xを使ってごらんよ、という悪魔の囁きに、2ヶ月も遅れて対応したという情けない事情により記述されたものです。(お二人とも、遅れてごめん!)。ちなみに、檜山正幸さんは[雑記/備忘]groovyのmarkup/node builderと混合内容:オマケのあたりでE4Xに言及されています。
インストール §
RhinoはJavaで記述されたJavaScript処理系なので、実行にJavaランタイムを必要とします。
こんなものに手を出すような人なら、まあ何か既にインストール済みでしょう。
私は、マシンに入っていた以下をそのまま利用。
D:\Documents and Settings\autumn>"D:\Program Files\Java\jdk1.5.0_03\jre\bin\java.exe" -version
java version "1.5.0_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_03-b07)
Java HotSpot(TM) Client VM (build 1.5.0_03-b07, mixed mode, sharing)
次に、E4Xに必要なXMLBeansを以下より落とします。
私はとりあえずxmlbeans-2.0.0を落としてみました。
落としたらlibディレクトリの中身の.jreファイルを、実行用のJREのlib\extディレクトリにコピーします。(なに、extディレクトリを安易に使ってはいけない? 私の場合、Javaはソフトの試用にしか使わないから問題なし。何かあればどうせすぐ消して入れ直すし。気になる人はclasspathを真面目に使え!)
次に、Rhino 1.6R1を以下より落とします。
これを適当なディレクトリに展開しておきます。
Rhino起動 §
以下のようなコマンドでRhinoを起動します。ディレクトリ名は適宜読み替えて使ってください。
D:\work>"D:\Program Files\Java\jdk1.5.0_03\jre\bin\java.exe" -jar D:\work\rhino1_6R1\js.jar
Rhino 1.6 release 1 2004 11 30
js>
ちなみに、javaコマンドはフルパスで指定する必要がありました。指定しないと、なぜかWindowsディレクトリに入っていたjava.exeが使われ、せっかく入れたXMLBeansのモジュールが発見できないような印象です。これ以上は主題ではないので、詳しく調べていません。(最近のJavaはほとんど使ってないので、良く分かりません。分かろうとするだけの魅力も感じないので、きっと分からないまま終わるでしょう)
E4Xの動作テスト §
"js>"がRhinoのプロンプトなので、これに続いてコードを打ち込むことができます。
まず、E4X抜きのECMAScriptの動作確認を。
js> print("Hello World!")
Hello World!
js>
こういう作業をしていると、まさに昔懐かしい1970年代のBASICを彷彿とさせます。打てばすぐリアクションがあるし、しかもキーワードはprintですから (笑。
さて、次はE4Xを動作させてみます。
まず、"a = <x><y>0</y>"リターンと打つと、更に続きを入力できます。そこで、"<y>1</y>"リターン、"<y>2</y></x>"と打ちます。これでXMLの要素が全て閉じるので、ここで入力が終わります。
その後、入力した値が出力されますが、自動的に書式整形されるので改行の入る位置は一致していません。見やすくて便利で良いですね。(副作用は怖いですが)
js> a = <x><y>0</y>
<y>1</y>
<y>2</y></x>
<x>
<y>0</y>
<y>1</y>
<y>2</y>
</x>
js>
次に変数aの内容を見ます。aリターンでOK。お気楽です。
js> a
<x>
<y>0</y>
<y>1</y>
<y>2</y>
</x>
js>
もっとE4Xで遊ぶ §
E4Xは単に変数にXML文書(正確にはXMLフラグメントらしい)が入っているだけではありません。
その一部へのアクセスも簡単。
ルートの子要素となるy要素だけ出力するには、a.yリターンと打つだけ。
js> a.y
<y>0</y>
<y>1</y>
<y>2</y>
js>
ちなみに、E4Xの言語仕様書は見てませんが、檜山さんの文章を見ると、ルートの要素は区切りのプレースホルダであって意味を持たないようです。つまり、x要素の存在は忘れて良いということで良いようです。
更に、3番目(インデックスが2)の要素だけにアクセスするなら、a.y[2]リターンと打つだけ。
要素内容の書き換えも簡単です。
たとえば、3番目(インデックスが2)の要素の内容を"999"に書き換えるには、a.y[2]="999"リターンと打つだけ。
$js> a.y[2]="999"
999
js> a
<x>
<y>0</y>
<y>1</y>
<y>999</y>
</x>
js>
実に簡単にXMLフラグメントツリーを操作できます。
感想 でも乗れないのはなぜ? §
こんなに簡単にXMLフラグメントを操作できて、嬉しくてたまらない……のかといえばそうではありません。
正直、直感的に理解できない動作をしてくれて、多大な試行錯誤を要しました。
たとえば、以下を見てください。
js> a1 = <a>Hello!</a>
Hello!
js> a2 = <a><b>Hello!</b></a>
<a>
<b>Hello!</b>
</a>
js>
a1の方は、出力の中にフラグメントのルートになる要素のタグが見えません。しかし、a2の方は見えます。両者の相違は子が要素かテキストかの違いに過ぎませんが、それにしては結果がかけ離れすぎています。
とはいえ、懸念は抱きつつも、言語仕様書を見ていない段階で確実なことは言えません。
仮にE4Xを採用することがあるとしても、言語仕様書を見て慎重な検討の上で、ということになると思います。
それ以前に…… §
実は、それ以前の問題として、こういう複数言語がコード上に混在する表記法は避けたいという気持ちがあります。分かりにくくトラブルが起こりやすいからです。
単にソースコードへXML文書を埋め込む「だけ」の話なら、うまくリテラルの構文を工夫して入れ込む方が好きですね。
たとえばC#を使って以下のような感じで。
using System;
using System.Xml;
class Sample
{
[STAThread]
static void Main(string[] args)
{
const string xmldoc = @"<x><y>0</y>
<y>1</y>
<y>2</y></x>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmldoc);
doc.Save(Console.Out);
}
}
もちろん、この表記もインデントがぐちゃぐちゃになるし、コンパイル時にXML文書の適合性をチェックできないので、満点にはほど遠いのですが。しかし、本来まったく別個に作成された言語を、区別することなく混在可能とする言語仕様よりは好ましいと感じます。感じるだけで何の根拠もないので、真面目に受け止める必要はありませんが (笑。
参考記事 §
Jon Udell's Weblog, Introduction to E4X